﻿using Infrastructure.FileFunction.Operation;
using System;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Infrastructure.FileFunction.Serialize
{
    /// <summary>
    /// 序列化为二进制
    /// </summary>
    public static class BinarySerializeUtil
    {
        /// <summary> 
        /// 将一个对象序列化，返回一个byte[]         
        /// </summary> 
        /// <param name="obj">能序列化的对象</param>         
        /// <returns></returns> 
        public static byte[] SerializerToBytes<T>(this T obj) where T : class
        {
            using (MemoryStream ms = new MemoryStream())
            {
                IFormatter formatter = new BinaryFormatter();
                formatter.Serialize(ms, obj);
                return ms.GetBuffer();
            }
        }

        /// <summary>
        /// 序列化文件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="dirPath"></param>
        /// <param name="fileName"></param>
        public static void SerializeToBinary<T>(this T obj, string dirPath, string fileName) where T : class
        {
            if (!FilesUtils.DirExists(dirPath))
            {
                FilesUtils.CreateDir(dirPath);
            }

            var filePath = $"{dirPath}\\{fileName}";

            using (FileStream fs = new FileStream(filePath, FileMode.Create))
            {
                BinaryFormatter formatter = new BinaryFormatter();

                formatter.Serialize(fs, obj);
            }
        }

        /// <summary> 
        /// 将一个序列化后的byte[]数组还原         
        /// </summary>
        /// <param name="bytes"></param>         
        /// <returns></returns> 
        public static T DeserializeBytes<T>(this byte[] bytes) where T : class
        {
            using (MemoryStream ms = new MemoryStream(bytes))
            {
                IFormatter formatter = new BinaryFormatter();
                return formatter.Deserialize(ms) as T;
            }
        }

        /// <summary>
        /// 反序列化文件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static T DeserializeBinary<T>(string filePath) where T : class
        {
            if (!FilesUtils.FileExistes(filePath))
            {
                throw new FileNotFoundException($"{filePath}不存在");
            }

            using (FileStream fs = new FileStream(filePath, FileMode.Open))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                return (T)formatter.Deserialize(fs);
            }

        }

        /// <summary>
        /// 反序列化文件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static T DeserializeBinaryOrDefault<T>(string filePath) where T : class
        {
            if (!FilesUtils.FileExistes(filePath))
            {
                return default(T);
            }

            try
            {
                using (FileStream fs = new FileStream(filePath, FileMode.Open))
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    return (T)formatter.Deserialize(fs);
                }
            }
            catch
            {
                return default(T);
            }
        }
    }
}
